/**
 * 
 */
package org.statewalker.template.dom;

import java.util.LinkedHashMap;
import java.util.Map;

import org.statewalker.template.XmlWriteUtil;
import org.statewalker.template.XmlTemplateRunner.IXmlAccessor;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.Text;

public class DomAccessor implements IXmlAccessor<Node> {

    public static void write(Node node, StringBuilder builder, boolean include) {
        if (node instanceof Element) {
            Element e = (Element) node;
            String name = e.getNodeName();
            if (include) {
                builder.append("<");
                builder.append(name);
                NamedNodeMap attrs = node.getAttributes();
                for (int i = 0; i < attrs.getLength(); i++) {
                    Attr attr = (Attr) attrs.item(i);
                    builder.append(" ");
                    XmlWriteUtil.escapeName(builder, attr.getName());
                    builder.append("='");
                    XmlWriteUtil.escapeName(builder, attr.getValue());
                    builder.append("'");
                }
                builder.append(">");

            }
            Node child = e.getFirstChild();
            while (child != null) {
                write(child, builder, true);
                child = child.getNextSibling();
            }
            if (include) {
                builder.append("</").append(name).append(">");
            }
        } else {
            if (node instanceof Text) {
                Text text = (Text) node;
                builder.append(text.getData());
            } else if (node instanceof Attr) {
                Attr attr = (Attr) node;
                builder.append(attr.getValue());
            }
        }
    }

    public Map<String, String> getAttributes(Node node) {
        if (!(node instanceof Element))
            return null;
        Element e = (Element) node;
        Map<String, String> result = new LinkedHashMap<String, String>();
        NamedNodeMap map = e.getAttributes();
        for (int i = 0; i < map.getLength(); i++) {
            Attr item = (Attr) map.item(i);
            String name = item.getName();
            String value = item.getValue();
            result.put(name, value);
        }
        return result;
    }

    public String getAttributeValue(Node node, String name) {
        Element element = (Element) node;
        Attr attr = element.getAttributeNode(name);
        return attr != null ? attr.getValue() : null;
    }

    public Node getFirstChild(Node node) {
        return node.getFirstChild();
    }

    public Node getNextSibling(Node node) {
        return node.getNextSibling();
    }

    public String getNodeName(Node node) {
        return node.getNodeName();
    }

    public boolean isElement(Node node) {
        return node instanceof Element;
    }

    public String toString(Node node) {
        StringBuilder builder = new StringBuilder();
        write(node, builder, true);
        return builder.toString();
    }

}